"""
文件名: channel.py
描述: YouTube频道数据模型定义

本模块包含以下主要功能：
1. Channel数据库模型 - SQLAlchemy ORM模型
2. ChannelCreate - 频道创建时的数据验证模型
3. ChannelUpdate - 频道更新时的数据验证模型
4. ChannelInDB - 数据库查询返回的频道模型
5. 频道相关的辅助方法和属性

依赖模块:
   - sqlalchemy: ORM框架和数据库操作
   - pydantic: 数据验证和序列化
   - datetime: 时间处理
   - typing: 类型注解

使用示例:
   >>> from src.models.channel import Channel, ChannelCreate
   >>> channel_data = ChannelCreate(
   ...     channel_id="UCxxxxx",
   ...     title="科技频道",
   ...     description="关于科技的频道"
   ... )
   >>> channel = Channel(**channel_data.dict())

注意事项:
   - 频道ID是YouTube提供的唯一标识符
   - 频道信息需要定期同步更新
   - 统计数据可能有延迟
   - 删除采用软删除方式

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from datetime import datetime
from typing import Optional, List

from sqlalchemy import Column, String, DateTime, Boolean, Text, Integer, BigInteger, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
import uuid

from pydantic import BaseModel, Field, validator, HttpUrl

from src.core.database import Base


class Channel(Base):
    """
    YouTube频道数据库模型
    
    存储从YouTube API获取的频道信息
    """
    __tablename__ = "channels"
    
    # 主键和基本信息
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    channel_id = Column(String(50), unique=True, index=True, nullable=False, comment="YouTube频道ID")
    title = Column(String(255), nullable=False, comment="频道标题")
    description = Column(Text, nullable=True, comment="频道描述")
    custom_url = Column(String(255), nullable=True, comment="自定义URL")
    
    # 频道元数据
    thumbnail_url = Column(Text, nullable=True, comment="频道头像URL")
    banner_url = Column(Text, nullable=True, comment="频道横幅URL")
    country = Column(String(10), nullable=True, comment="频道所在国家")
    default_language = Column(String(10), nullable=True, comment="默认语言")
    
    # 统计信息
    subscriber_count = Column(BigInteger, default=0, nullable=False, comment="订阅者数量")
    video_count = Column(Integer, default=0, nullable=False, comment="视频数量")
    view_count = Column(BigInteger, default=0, nullable=False, comment="总观看次数")
    
    # 频道状态
    is_active = Column(Boolean, default=True, nullable=False, comment="频道是否活跃")
    privacy_status = Column(String(20), default="public", nullable=False, comment="隐私状态")
    upload_playlist_id = Column(String(50), nullable=True, comment="上传播放列表ID")
    
    # 同步相关
    last_video_published_at = Column(DateTime(timezone=True), nullable=True, comment="最新视频发布时间")
    last_sync_at = Column(DateTime(timezone=True), nullable=True, comment="最后同步时间")
    sync_status = Column(String(20), default="pending", nullable=False, comment="同步状态")
    sync_error = Column(Text, nullable=True, comment="同步错误信息")
    
    # 额外信息（JSON格式）
    keywords = Column(JSONB, nullable=True, comment="频道关键词")
    topic_details = Column(JSONB, nullable=True, comment="主题详情")
    branding_settings = Column(JSONB, nullable=True, comment="品牌设置")
    
    # 时间戳
    created_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        nullable=False,
        comment="创建时间"
    )
    updated_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        onupdate=func.now(),
        nullable=False,
        comment="更新时间"
    )
    deleted_at = Column(DateTime(timezone=True), nullable=True, comment="删除时间（软删除）")
    
    # 关系映射
    # user_channels = relationship("UserChannel", back_populates="channel")
    # videos = relationship("Video", back_populates="channel")
    
    def __repr__(self) -> str:
        return f"<Channel(id={self.id}, channel_id={self.channel_id}, title={self.title})>"
    
    @property
    def is_deleted(self) -> bool:
        """检查频道是否被删除"""
        return self.deleted_at is not None
    
    @property
    def subscriber_count_display(self) -> str:
        """格式化显示订阅者数量"""
        if self.subscriber_count >= 1_000_000:
            return f"{self.subscriber_count / 1_000_000:.1f}M"
        elif self.subscriber_count >= 1_000:
            return f"{self.subscriber_count / 1_000:.1f}K"
        else:
            return str(self.subscriber_count)
    
    @property
    def is_sync_needed(self) -> bool:
        """判断是否需要同步"""
        if not self.last_sync_at:
            return True
        # 如果超过1小时未同步，则需要同步
        return (datetime.utcnow() - self.last_sync_at).total_seconds() > 3600


class ChannelBase(BaseModel):
    """频道基础数据模型"""
    channel_id: str = Field(..., min_length=1, max_length=50, description="YouTube频道ID")
    title: str = Field(..., min_length=1, max_length=255, description="频道标题")
    description: Optional[str] = Field(None, description="频道描述")
    custom_url: Optional[str] = Field(None, max_length=255, description="自定义URL")
    thumbnail_url: Optional[str] = Field(None, description="频道头像URL")
    banner_url: Optional[str] = Field(None, description="频道横幅URL")
    country: Optional[str] = Field(None, max_length=10, description="频道所在国家")
    default_language: Optional[str] = Field(None, max_length=10, description="默认语言")
    
    class Config:
        from_attributes = True


class ChannelCreate(ChannelBase):
    """频道创建数据模型"""
    subscriber_count: Optional[int] = Field(0, ge=0, description="订阅者数量")
    video_count: Optional[int] = Field(0, ge=0, description="视频数量") 
    view_count: Optional[int] = Field(0, ge=0, description="总观看次数")
    privacy_status: Optional[str] = Field("public", description="隐私状态")
    upload_playlist_id: Optional[str] = Field(None, max_length=50, description="上传播放列表ID")
    keywords: Optional[List[str]] = Field(None, description="频道关键词")
    topic_details: Optional[dict] = Field(None, description="主题详情")
    
    @validator("channel_id")
    def validate_channel_id(cls, v):
        """验证频道ID格式"""
        if not v or not v.startswith(("UC", "HC", "UU")):
            raise ValueError("频道ID格式无效")
        return v
    
    @validator("privacy_status")
    def validate_privacy_status(cls, v):
        """验证隐私状态"""
        valid_statuses = ["public", "private", "unlisted"]
        if v and v not in valid_statuses:
            raise ValueError(f"隐私状态必须是: {', '.join(valid_statuses)}")
        return v


class ChannelUpdate(BaseModel):
    """频道更新数据模型"""
    title: Optional[str] = Field(None, min_length=1, max_length=255, description="频道标题")
    description: Optional[str] = Field(None, description="频道描述")
    custom_url: Optional[str] = Field(None, max_length=255, description="自定义URL")
    thumbnail_url: Optional[str] = Field(None, description="频道头像URL")
    banner_url: Optional[str] = Field(None, description="频道横幅URL")
    country: Optional[str] = Field(None, max_length=10, description="频道所在国家")
    default_language: Optional[str] = Field(None, max_length=10, description="默认语言")
    subscriber_count: Optional[int] = Field(None, ge=0, description="订阅者数量")
    video_count: Optional[int] = Field(None, ge=0, description="视频数量")
    view_count: Optional[int] = Field(None, ge=0, description="总观看次数")
    is_active: Optional[bool] = Field(None, description="频道是否活跃")
    privacy_status: Optional[str] = Field(None, description="隐私状态")
    upload_playlist_id: Optional[str] = Field(None, max_length=50, description="上传播放列表ID")
    last_video_published_at: Optional[datetime] = Field(None, description="最新视频发布时间")
    last_sync_at: Optional[datetime] = Field(None, description="最后同步时间")
    sync_status: Optional[str] = Field(None, description="同步状态")
    sync_error: Optional[str] = Field(None, description="同步错误信息")
    keywords: Optional[List[str]] = Field(None, description="频道关键词")
    topic_details: Optional[dict] = Field(None, description="主题详情")
    
    @validator("privacy_status")
    def validate_privacy_status(cls, v):
        """验证隐私状态"""
        if v is not None:
            valid_statuses = ["public", "private", "unlisted"]
            if v not in valid_statuses:
                raise ValueError(f"隐私状态必须是: {', '.join(valid_statuses)}")
        return v
    
    @validator("sync_status")
    def validate_sync_status(cls, v):
        """验证同步状态"""
        if v is not None:
            valid_statuses = ["pending", "syncing", "success", "failed"]
            if v not in valid_statuses:
                raise ValueError(f"同步状态必须是: {', '.join(valid_statuses)}")
        return v
    
    class Config:
        from_attributes = True


class ChannelInDB(ChannelBase):
    """数据库查询返回的频道模型"""
    id: uuid.UUID = Field(..., description="频道内部ID")
    subscriber_count: int = Field(..., description="订阅者数量")
    video_count: int = Field(..., description="视频数量")
    view_count: int = Field(..., description="总观看次数")
    is_active: bool = Field(..., description="频道是否活跃")
    privacy_status: str = Field(..., description="隐私状态")
    upload_playlist_id: Optional[str] = Field(None, description="上传播放列表ID")
    last_video_published_at: Optional[datetime] = Field(None, description="最新视频发布时间")
    last_sync_at: Optional[datetime] = Field(None, description="最后同步时间")
    sync_status: str = Field(..., description="同步状态")
    sync_error: Optional[str] = Field(None, description="同步错误信息")
    keywords: Optional[List[str]] = Field(None, description="频道关键词")
    topic_details: Optional[dict] = Field(None, description="主题详情")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")
    
    @property
    def subscriber_count_display(self) -> str:
        """格式化显示订阅者数量"""
        if self.subscriber_count >= 1_000_000:
            return f"{self.subscriber_count / 1_000_000:.1f}M"
        elif self.subscriber_count >= 1_000:
            return f"{self.subscriber_count / 1_000:.1f}K"
        else:
            return str(self.subscriber_count)


class ChannelStats(BaseModel):
    """频道统计信息模型"""
    subscriber_count: int = Field(..., description="订阅者数量")
    video_count: int = Field(..., description="视频数量")
    view_count: int = Field(..., description="总观看次数")
    last_video_published_at: Optional[datetime] = Field(None, description="最新视频发布时间")
    subscriber_count_display: str = Field(..., description="格式化的订阅者数量")
    
    class Config:
        from_attributes = True


class ChannelSummary(BaseModel):
    """频道摘要信息模型（列表页面使用）"""
    id: uuid.UUID = Field(..., description="频道内部ID")
    channel_id: str = Field(..., description="YouTube频道ID")
    title: str = Field(..., description="频道标题")
    thumbnail_url: Optional[str] = Field(None, description="频道头像URL")
    subscriber_count: int = Field(..., description="订阅者数量")
    video_count: int = Field(..., description="视频数量")
    last_video_published_at: Optional[datetime] = Field(None, description="最新视频发布时间")
    sync_status: str = Field(..., description="同步状态")
    
    @property
    def subscriber_count_display(self) -> str:
        """格式化显示订阅者数量"""
        if self.subscriber_count >= 1_000_000:
            return f"{self.subscriber_count / 1_000_000:.1f}M"
        elif self.subscriber_count >= 1_000:
            return f"{self.subscriber_count / 1_000:.1f}K"
        else:
            return str(self.subscriber_count)
    
    class Config:
        from_attributes = True